/* 
	*************************************************************************

	LogServer.h

	Author:    Matthias Gudmundsson
	Created:   June. 1998
	OS:        Win32
	Project:   Utilities - Logger

	Description:   

		Logging utility - server side


		!!! ATTENTION !!!
		All changes to this file must be replicated in C_LogServer.pas


	(c) OZ Interactive Inc. 1998

	*************************************************************************
*/

#ifndef LOGSERVER_H
#define LOGSERVER_H

#pragma once

#ifndef STRICT
#define STRICT
#endif


#include <windows.h>
#include "Logger.h"


//////////////////////////////////////////////////////////
//  types and consts and stuff...
//////////////////////////////////////////////////////////

#pragma pack(push, logger, 8) //need a specific packing for IPC


const DWORD LOG_VERSION =			MAKELONG(0, 7);	// version number: low, high

const int LOG_MAXFACILITYDESC =		32;		// max. length of facility description
const int LOG_MAXOBJECTDESC =		32;		// max. length of object description
const int LOG_MAXMESSAGE =			255;	// max. length of log message

const int LOG_MAXCHANNELS =			1000;	// max. number of log channels

//////////////////////////////////////////////////////////
//  structs and stuff...
//////////////////////////////////////////////////////////
typedef char TMODULENAME[MAX_PATH];
typedef char TPROCESSNAME[MAX_PATH];
typedef char TLOGFACILITY[LOG_MAXFACILITYDESC+1];
typedef char TLOGOBJECTDESC[LOG_MAXOBJECTDESC+1];
typedef LARGE_INTEGER TLOGTIMESTAMP;
typedef __int64 TLOGOBJECTHASH;
typedef char TLOGCOMPUTERNAME[31];


typedef enum TLOGFN
{
	LOGFN_INITIALIZE =				1,		// function id for "initialize"
	LOGFN_TRACEMESSAGE =			2,		// function id for "trace message"
} TLOGFN;



typedef struct TLOGINITIALIZE
{
	// in params
	TLOGCOMPUTERNAME	computer;			// name of client computer
	TPROCESSNAME		processname;		// process filename
	DWORD				pid;				// process ID
	DWORD				module;				// module id (can't be HMODULE, that is a pointer and then we have 64 bit problems)
	TMODULENAME			modulename;			// module filename
	TLOGTIMESTAMP		starttime;			// start time
} TLOGINITIALIZE;


typedef char TLOGMESSAGESTR[LOG_MAXMESSAGE];

typedef struct TLOGTRACEMESSAGE
{
	// in params
	TLOGFLAG		flag;					// severity flag
	TLOGMESSAGESTR	msg;					// the log message
	DWORD			pid;					// process ID (here to make logserver faster)
} TLOGTRACEMESSAGE;




typedef struct TLOGFUNCTION
{
	TLOGCHANNELID		channel;			// index into channel buffer
	DWORD				tid;				// thread ID
	TLOGTIMESTAMP		timestamp;			// timestamp
	TLOGFN				fntype;				// function identifier
	TLOGSOURCEID		source;				// unique id to find initialize data
	
	union
	{
		TLOGINITIALIZE		init;
		TLOGTRACEMESSAGE	msg;
	};
    
} TLOGFUNCTION;


typedef struct TLOGCHANNELINFO
{
	TLOGOBJECTHASH		facilityhash;
	TLOGOBJECTHASH		objecthash;
	TLOGFACILITY		facility;			// name of facility
	TLOGOBJECTDESC		objectdesc;			// name of object
	long				suppressed;
	long				flagsuppress;
} TLOGCHANNELINFO;


typedef TLOGCHANNELINFO TLOGCHANNELINFOS[LOG_MAXCHANNELS];


typedef struct TLOGCHANNELS
{
	TLOGSOURCEID		counter;			// unique id for 'source' var
	TLOGCHANNELID		numchannels;
	TLOGCHANNELINFOS	channels;
} TLOGCHANNELS;

typedef struct TLOGBUFFHEADER
{
	DWORD				version;			// the value of LOG_VERSION
	DWORD				capacity;			// log queue's capacity
	DWORD				numRecs;			// number of logs in queue
	
	TLOGCHANNELS		logchannels;		// log channels

} TLOGBUFFHEADER;


typedef struct TLOGSERVERVAR
{
	// initialized by caller
	LPCSTR				mapfilename;		// name of file mapping obj. or NULL for def.
	DWORD				capacity;			// log queue capacity
	void				*cookie;			// used by apps, not used by this logger

	// initialized by LogRegisterServer
	HANDLE				mapfile;			// handle to the file mapping 
	TLOGBUFFHEADER		*sharedMemory;		// pointer to the shared memory
	TLOGFUNCTION		*nextAvailMem;		// pointer to next avail. mem.
	HANDLE				startSignal;		// used to signal flush
	HANDLE				waitSignal;			// used to signal completion of flush
	HANDLE				mutexA;				// used for exclusive access to shared mem.
	HANDLE				mutexB;				// used for exclusive access to shared mem.
} TLOGSERVERVAR;


typedef struct TLOGDEVNAMES
{
	char filemapname[30];
	char mutexnamea[30];
	char mutexnameb[30];
	char fulleventname[30];
	char flusheventname[30];
} TLOGDEVNAMES;


//use:	xxxx
#define NextLogFn(shmem)	\
	(TLOGFUNCTION *)((char *)shmem + sizeof(TLOGBUFFHEADER) + \
	(sizeof(TLOGFUNCTION) * shmem->numRecs))


//use:	LogInitDevNames(basename);
//pre:	strlen(basename) <= 20
//post:	Logdevice registered to name 'basename'
void LogInitDevNames(const char *basename, TLOGDEVNAMES &names);


//use:	err = LogRegisterServer(lsv);
//pre:	'lsv.capacity' > 0 and LogInitDevice has been called
//post:	if 'err' is ERROR_SUCCESS, then 'lsv.startSignal' is a waitable object which will
//		be signaled whenever the log queue is full, else 'err' is a Win32 error.
//		the log queueu is associated with the name identified by 'lsv.mapfilename', but
//		if 'lsv.mapfilename' is NULL, then the default name is used.
int WINAPI LogRegisterServer(TLOGSERVERVAR&);


//use:	LogUnregisterServer(lsv);
//pre:	LogRegisterServer has been called successfully with 'lsv'
//post:	all IPC objects have been released
void WINAPI LogUnregisterServer(TLOGSERVERVAR&);


//remark:	this application-defined callback function is called in response to a call
//			to FlushQueue.  The implementation should iterate through all log entries
//			like this:
//
//	void OnLog(LOGSERVERVAR& lsv)
//	{
//		LOGFUNCTION* fn = (LOGFUNCTION*)((char*)header + sizeof(LOGBUFFHEADER));
//		
//		for (unsigned i = 0; i < lsv.sharedMemroy.numRecs; i++)
//		{
//			// do whatever with fn
//			fn++;
//		}
//	}

typedef void (WINAPI *LOGFN)(TLOGSERVERVAR&);


//use:	FlushQueue(lsv, OnLog);
//pre:	LogRegisterServer has been called successfully with 'lsv'
//post:	'OnLog' was called with 'lsv'.  the log queue is empty
//remark:	this function may be called as many times as seems fit, i.e.
//			'lsv.startSignal' does not have to be signaled.
void WINAPI FlushQueue(TLOGSERVERVAR&, LOGFN);

#pragma pack(pop, logger)

#endif // LOGSERVER_H

